
<!DOCTYPE html>
<html lang="en">
    <head>

    <title>ILRuntime中跨域继承 — ILRuntime</title>
    <meta charset="utf-8">
    <meta name="description" content="ILRuntime">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

    <link rel="stylesheet" href="/ILRuntime/public/css/page.css">

    <script src="/ILRuntime/public/js/vue.js"></script>
    <script src="/ILRuntime/public/js/jquery.js"></script>
    </head>

    <body>
        
            <nav class="nav">
    <div class="border">
        <img src="/ILRuntime/public/images/logo.png" />
        <button class="hiden-in-phone">V1.3</button>
        <button id="btn-menu" class="hiden-in-pc">菜单</button>
        <ul class="nav-link hiden-in-phone">
            <!--li>
                <form id="search-form">
                    <input type="text" id="search-query" class="search-query">
                </form>
            </li!-->
            <li><a href="https://github.com/Ourpalm/ILRuntime" class="nav-link-li">下载项目</a></li>
            <li><a href="/ILRuntime/public/v1/guide/use.html" class="nav-link-li">使用案例</a></li>
            <li><a href="/ILRuntime/public/v1/guide/version.html" class="nav-link-li">更新记录</a></li>
            <li><a href="/ILRuntime/public/v1/guide/contribution.html" class="nav-link-li">贡献指南</li>
            <li><a href="/ILRuntime/public/v1/guide/index.html" class="nav-link-li">教程</a></li>
            <li><a href="/ILRuntime/public/" class="nav-link-li current">首页</a></li>
        </ul>
    </div>
</nav>

<div id="container" class="container clear">
    <section class="sidebar clearfix">
    <ul>
        
            
            
                <li><h3>基础</h3></li>
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/index.html" class="sidebar-link">介绍</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/version.html" class="sidebar-link">更新记录</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/use.html" class="sidebar-link">商业案例</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/contribution.html" class="sidebar-link">贡献指南</a></p>
            </li>
        
            
            
            
                <li><h3>教程</h3></li>
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/tutorial.html" class="sidebar-link">从零开始</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/delegate.html" class="sidebar-link">ILRuntime中使用委托</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/cross-domain.html" class="sidebar-link current">ILRuntime中跨域继承</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/reflection.html" class="sidebar-link">ILRuntime中的反射</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/redirection.html" class="sidebar-link">CLR重定向</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/bind.html" class="sidebar-link">CLR绑定</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/litjson.html" class="sidebar-link">LitJson集成</a></p>
            </li>
        
            
            
            
            
                <li><h3>其他</h3></li>
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/il2cpp.html" class="sidebar-link">IL2CPP打包注意事项</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/performance-optimization.html" class="sidebar-link">ILRuntime的性能优化</a></p>
            </li>
        
            
            
            
            
            <li>
                <p><a href="/ILRuntime/public/v1/guide/principle.html" class="sidebar-link">ILRuntime的实现原理</a></p>
            </li>
        
    </ul>
</section>
    <article class="clearfix">
    <h2 id="ILRuntime中跨域继承"><a href="#ILRuntime中跨域继承" class="headerlink" title="ILRuntime中跨域继承"></a>ILRuntime中跨域继承</h2><p>如果你想在热更DLL项目当中<code>继承一个Unity主工程里的类</code>，或者<code>实现一个主工程里的接口</code>，你需要在Unity主工程中实现一个继承适配器。<br>方法如下：</p>
<figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line"> <span class="comment">//你想在DLL中继承的那个类</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title">ClassInheritanceTest</span></div><div class="line"> &#123;</div><div class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title">TestAbstract</span>(<span class="params"></span>)</span>;</div><div class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">TestVirtual</span>(<span class="params">ClassInheritanceTest a</span>)</span></div><div class="line"><span class="function">     </span>&#123;</div><div class="line">         </div><div class="line">     &#125;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="comment">//这个类就是继承适配器类</span></div><div class="line"> <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">ClassInheritanceAdaptor</span> : <span class="title">CrossBindingAdaptor</span></div><div class="line"> &#123;</div><div class="line">     <span class="keyword">public</span> <span class="keyword">override</span> Type BaseCLRType</div><div class="line">     &#123;</div><div class="line">         <span class="keyword">get</span></div><div class="line">         &#123;</div><div class="line">    <span class="comment">//如果你是想一个类实现多个Unity主工程的接口，这里需要return null;</span></div><div class="line">             <span class="keyword">return</span> <span class="keyword">typeof</span>(ClassInheritanceTest);<span class="comment">//这是你想继承的那个类</span></div><div class="line">         &#125;</div><div class="line">     &#125;</div><div class="line">		</div><div class="line">     <span class="keyword">public</span> <span class="keyword">override</span> Type[] BaseCLRTypes</div><div class="line">     &#123;</div><div class="line">         <span class="keyword">get</span></div><div class="line">         &#123;</div><div class="line">             <span class="comment">//跨域继承只能有1个Adapter，因此应该尽量避免一个类同时实现多个外部接口，</span></div><div class="line">             <span class="comment">//ILRuntime虽然支持同时实现多个接口，但是一定要小心这种用法，使用不当很容易造成不可预期的问题</span></div><div class="line">             <span class="comment">//日常开发如果需要实现多个DLL外部接口，请在Unity这边先做一个基类实现那些个接口，然后继承那个基类</span></div><div class="line">	<span class="comment">//如需一个Adapter实现多个接口，请用下面这行</span></div><div class="line">             <span class="comment">//return new Type[] &#123; typeof(IEnumerator&lt;object&gt;), typeof(IEnumerator), typeof(IDisposable) &#125;;</span></div><div class="line">	<span class="keyword">return</span> <span class="literal">null</span>;</div><div class="line">         &#125;</div><div class="line">     &#125;</div><div class="line"></div><div class="line">     <span class="keyword">public</span> <span class="keyword">override</span> Type AdaptorType</div><div class="line">     &#123;</div><div class="line">         <span class="keyword">get</span></div><div class="line">         &#123;</div><div class="line">             <span class="keyword">return</span> <span class="keyword">typeof</span>(Adaptor);<span class="comment">//这是实际的适配器类</span></div><div class="line">         &#125;</div><div class="line">     &#125;</div><div class="line"></div><div class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">object</span> <span class="title">CreateCLRInstance</span>(<span class="params">ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance</span>)</span></div><div class="line"><span class="function">     </span>&#123;</div><div class="line">         <span class="keyword">return</span> <span class="keyword">new</span> Adaptor(appdomain, instance);<span class="comment">//创建一个新的实例</span></div><div class="line">     &#125;</div><div class="line"></div><div class="line">     <span class="comment">//实际的适配器类需要继承你想继承的那个类，并且实现CrossBindingAdaptorType接口</span></div><div class="line">     class Adaptor : ClassInheritanceTest,CrossBindingAdaptorType</div><div class="line">     &#123;</div><div class="line">         ILTypeInstance instance;</div><div class="line">         ILRuntime.Runtime.Enviorment.AppDomain appdomain;</div><div class="line">         IMethod mTestAbstract;</div><div class="line"><span class="keyword">bool</span> mTestAbstractGot;</div><div class="line">         IMethod mTestVirtual;</div><div class="line"><span class="keyword">bool</span> mTestVirtualGot;</div><div class="line">         <span class="keyword">bool</span> isTestVirtualInvoking = <span class="literal">false</span>;</div><div class="line"><span class="comment">//缓存这个数组来避免调用时的GC Alloc</span></div><div class="line"><span class="keyword">object</span>[] param1 = <span class="keyword">new</span> <span class="keyword">object</span>[<span class="number">1</span>];</div><div class="line"></div><div class="line">         <span class="function"><span class="keyword">public</span> <span class="title">Adaptor</span>(<span class="params"></span>)</span></div><div class="line"><span class="function">         </span>&#123;</div><div class="line"></div><div class="line">         &#125;</div><div class="line"></div><div class="line">         <span class="function"><span class="keyword">public</span> <span class="title">Adaptor</span>(<span class="params">ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance</span>)</span></div><div class="line"><span class="function">         </span>&#123;</div><div class="line">             <span class="keyword">this</span>.appdomain = appdomain;</div><div class="line">             <span class="keyword">this</span>.instance = instance;</div><div class="line">         &#125;</div><div class="line"></div><div class="line">         <span class="keyword">public</span> ILTypeInstance ILInstance &#123; <span class="keyword">get</span> &#123; <span class="keyword">return</span> instance; &#125; &#125;</div><div class="line">         </div><div class="line"><span class="comment">//你需要重写所有你希望在热更脚本里面重写的方法，并且将控制权转到脚本里去</span></div><div class="line">         <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">TestAbstract</span>(<span class="params"></span>)</span></div><div class="line"><span class="function">         </span>&#123;</div><div class="line">             <span class="keyword">if</span>(!mTestAbstractGot)</div><div class="line">             &#123;</div><div class="line">                 mTestAbstract = instance.Type.GetMethod(<span class="string">"TestAbstract"</span>, <span class="number">0</span>);</div><div class="line">		mTestAbstractGot = <span class="literal">true</span>;</div><div class="line">             &#125;</div><div class="line">             <span class="keyword">if</span> (mTestAbstract != <span class="literal">null</span>)</div><div class="line">                 appdomain.Invoke(mTestAbstract, instance, <span class="literal">null</span>);<span class="comment">//没有参数建议显式传递null为参数列表，否则会自动new object[0]导致GC Alloc</span></div><div class="line">         &#125;</div><div class="line"></div><div class="line">         <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">TestVirtual</span>(<span class="params">ClassInheritanceTest a</span>)</span></div><div class="line"><span class="function">         </span>&#123;</div><div class="line">             <span class="keyword">if</span> (!mTestVirtualGot)</div><div class="line">             &#123;</div><div class="line">                 mTestVirtual = instance.Type.GetMethod(<span class="string">"TestVirtual"</span>, <span class="number">1</span>);</div><div class="line">		mTestVirtualGot = <span class="literal">true</span>;</div><div class="line">             &#125;</div><div class="line">	<span class="comment">//对于虚函数而言，必须设定一个标识位来确定是否当前已经在调用中，否则如果脚本类中调用base.TestVirtual()就会造成无限循环，最终导致爆栈</span></div><div class="line">             <span class="keyword">if</span> (mTestVirtual != <span class="literal">null</span> &amp;&amp; !isTestVirtualInvoking)</div><div class="line">             &#123;</div><div class="line">                 isTestVirtualInvoking = <span class="literal">true</span>;</div><div class="line">		param1[<span class="number">0</span>] = a;</div><div class="line">                    appdomain.Invoke(mTestVirtual, instance, <span class="keyword">this</span>.param1);</div><div class="line">                 isTestVirtualInvoking = <span class="literal">false</span>;</div><div class="line">             &#125;</div><div class="line">             <span class="keyword">else</span></div><div class="line">                 <span class="keyword">base</span>.TestVirtual(a);</div><div class="line">         &#125;</div><div class="line"></div><div class="line">         <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">string</span> <span class="title">ToString</span>(<span class="params"></span>)</span></div><div class="line"><span class="function">         </span>&#123;</div><div class="line">             IMethod m = appdomain.ObjectType.GetMethod(<span class="string">"ToString"</span>, <span class="number">0</span>);</div><div class="line">             m = instance.Type.GetVirtualMethod(m);</div><div class="line">             <span class="keyword">if</span> (m == <span class="literal">null</span> || m <span class="keyword">is</span> ILMethod)</div><div class="line">             &#123;</div><div class="line">                 <span class="keyword">return</span> instance.ToString();</div><div class="line">             &#125;</div><div class="line">             <span class="keyword">else</span></div><div class="line">                 <span class="keyword">return</span> instance.Type.FullName;</div><div class="line">         &#125;</div><div class="line">     &#125;</div></pre></td></tr></table></figure>

    <div class="footer">
        发现错误？想参与编辑？ 
        <a href="https://github.com/Ourpalm/ILRuntime/tree/master/docs/source/src/v1/guide/cross-domain.md" target="_blank">
            在 Github 上编辑此页！
        </a>
    </div>
</article>

<div class="sub-nav hiden-in-phone">
    <dl id="sub-nav">
        <dt>本文内容</dt>
        <dd v-for="(ele, index) in sub_nav">
           <a v-bind:href="ele.href">{{ ele.name }}</a>
        </dd>
    </dl>
</div> 
</div>

<footer>
    <div>
        <p>© Copyright 2017 Ourpalm All Rights Reserved</p>
        <p>掌趣科技2017</p>
    </div>
</footer>


<script>
var vm = new Vue({
    el : '#container',
    data: {
        sub_nav : [ ]
    },
    created:function(){
        var obj = [];
        $("article h3").each(function(){
            obj.push({name :  $(this).find("a").attr("title") , href : "#"+$(this).attr("id") });
        });

        this.sub_nav = obj;       
    }
});

var isShow = false;
$("nav").on("click","#btn-menu" , function(){

    if(!isShow){
        
        if($(document).scrollTop() > $(".sidebar").height() - 100){

            $('html, body').animate({scrollTop:0} , 300, "swing",function(){

                $(".sidebar").fadeIn();
                $(".container").animate({"left" : "15rem"}, 500,"swing");
            });
        }else{

                $(".sidebar").fadeIn();
                $(".container").animate({"left" : "15rem"}, 500,"swing");

        }

    }else{
        $(".sidebar").fadeOut();
        $(".container").animate({"left" : "0rem"}, 500,"swing");
    }
    isShow = !isShow;

});

$(".container").on("click" , "article" , function(){

    if(isShow){
        $(".sidebar").fadeOut();
        $(".container").animate({"left" : "0rem"}, 500,"swing");
        isShow = false;    
    }

});
</script>
        
    </body>
</html>